"""
This module is used to create a configuration window for the
user to change settings for LIME.
"""
"""
   Copyright 2011 Gabriel Elkind and Brian Gapinski

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
"""
import logging
import os
import ConfigParser

import wx

logger = logging.getLogger('config')
class Config(wx.Frame):
    """
    This class stores all information that pertains to the user's
    preferences. As of now, this includes the location to Landis-II
    executable.

    @type _lime: wx.Frame
    @ivar _lime: The GUI container for the LII project

    @type _config: string
    @ivar _config: The file that stores the config settings

    @type _cp: ConfigParser
    @ivar _cp: ConfigParser used to read and edit the config file

    @type _path: string
    @ivar _path: The path to the LII executable

    @type _autosave: bool
    @ivar _autosave: True if LIME should autosave files when the user runs
                     the program, False otherwise

    @type _new_path: wx.TextCtrl
    @ivar _new_path: The new path to the LII exe

    @type _cb1: wx.CheckBox
    @ivar _cb1: The checkbox used to get the autosave state
    """
    def __init__(self, lime):
        """
        This module is meant to handle all user preferences for the
        LIME program.
        """
        logger.debug('Config initiated')
        wx.Frame.__init__(self, 
                          lime, 
                          wx.ID_ANY, 
                          'Config',
                          style=wx.FRAME_FLOAT_ON_PARENT|wx.DEFAULT_FRAME_STYLE,
                          size=(400,150))
        self._lime = lime
        self._new_path = None
        self._config = os.path.join(os.path.expanduser('~'), '.limerc')
        self._cp = ConfigParser.RawConfigParser()
        self._cp.read(self._config)
        self._path = ''
        self._autosave = False

        # Checks if the 'Path' section already exists
        if self._cp.has_section('Path'):
            logger.debug('Getting path from config file')
            self._path = self._cp.get('Path', 'exe')
            logger.debug('Path is %s', self._path)
            
            self._autosave = self._cp.getboolean('Flags', 'autosave')

        # Creates a new section if it does not
        else:
            logger.debug('Path not in config file')
            self._cp.add_section('Path')
            self._cp.add_section('Flags')
            self.ChangePref()

        self._InitUI()

        self.Bind(wx.EVT_CLOSE, self._OnCancel, self)

    def _InitUI(self):
        """
        Creates the interface for the user to modify preferences.
        """
        #Might make this part more dynamic, being created only
        #when the user decides to change preferences
        panel = wx.Panel(self)
        sizer = wx.GridBagSizer(5,5)
        
        text1 = wx.StaticText(panel, label='Landis-II exe')
        sizer.Add(text1, pos=(1,0))
        
        self._new_path = wx.TextCtrl(panel)
        sizer.Add(self._new_path, pos=(1,1), span=(1,3), flag=wx.EXPAND)
        
        button1 = wx.Button(panel, label='Browse...')
        sizer.Add(button1, pos=(1,4))

        self._cb1 = wx.CheckBox(panel, label='Autosave on run')
        sizer.Add(self._cb1, pos=(2,0), span=(1,5))
        self._cb1.SetValue(self._autosave)

        button2 = wx.Button(panel, label='Ok')
        sizer.Add(button2, pos=(3,4))

        button3 = wx.Button(panel, label='Cancel')
        sizer.Add(button3, pos=(3,3))

        sizer.AddGrowableCol(1)

        self.Bind(wx.EVT_BUTTON, self._OnBrowse, button1)
        self.Bind(wx.EVT_BUTTON, self._OnOk, button2)
        self.Bind(wx.EVT_BUTTON, self._OnCancel, button3)

        panel.SetSizerAndFit(sizer)

    def ChangePref(self):
        """
        Displays the preferences window so that the user can modify
        preferences through a graphical display.
        """
        if self._new_path:
            self._new_path.Remove(0,-1)
            self._new_path.AppendText(self._path)
            self.MakeModal(True)
            self.Centre()
            self.Show()

    def _SetDefaultPath(self):
        """
        This function is used to get the path to the executable
        of Landis-II.
        """
        logger.debug('Getting exe path')
        text = 'Please select the Landis-II executable'
        wcd = 'All files (*)|*|Text files (*.txt)|*.txt|'
        new_path = wx.FileDialog(None,
                                 message=text,
                                 defaultDir=os.path.expanduser('~'),
                                 defaultFile='',
                                 wildcard=wcd,
                                 style=wx.FD_OPEN)
        new_path.ShowModal()
        new_path = new_path.GetPath()
        return new_path

    def _SaveChanges(self):
        """
        Writes changes in the user's preferences to the .limerc file.
        """
        logger.debug('Saving the new changes to config file')
        self._cp.set('Path', 'exe', self._path)
        self._cp.set('Flags', 'autosave', self._autosave)
        with open(self._config, 'wb') as configfile:
            self._cp.write(configfile)
        

    def GetPath(self):
        """
        Returns the path to the Landis-II executable

        @return: The path to the Landis-II executable
        @rtype: string
        """
        return self._path

    def GetAutosave(self):
        """
        Returns the value of the _autosave instance variable.

        @rtype: bool
        @return: True if autosave on run is enabled, False otherwise.
        """
        return self._autosave

    def _OnBrowse(self, event):
        """
        Allows the user to select an executable from a file dialog
        """
        self._new_path.Remove(0,-1)
        self._new_path.AppendText(self._SetDefaultPath())

    def _OnOk(self, event):
        """
        Saves the user's selection
        """
        if self._new_path.GetValue().endswith('Landis.Console.exe'):
            self._path = self._new_path.GetValue()
            self._autosave = self._cb1.GetValue()
            self._SaveChanges()
            self._lime.ChangePref()
            self.MakeModal(False)
            self.Hide()
        else:
            self._BadPath()         

    def _BadPath(self):
        """
        Displays when the user has chosen a bad path to the
        Landis-II executable.
        """
        message = 'The path to the Landis-II executable is not valid! '
        message += 'Make sure to select Landis.Console.exe (make sure '
        message += 'it is the application and not the config!)'
        display = wx.MessageDialog(self, message, style=wx.OK)
        display.ShowModal()

    def _OnCancel(self, event):
        """
        Discards the user's changes
        """
        self.MakeModal(False)
        self.Hide()
